package br.edu.ifrn.mb;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.faces.event.ActionEvent;

import org.apache.myfaces.custom.fileupload.UploadedFile;

import br.edu.ifrn.dao.AreaAtuacaoDAO;
import br.edu.ifrn.dao.DiretoriaDAO;
import br.edu.ifrn.dao.UsuarioDAO;
import br.edu.ifrn.dominio.AreaAtuacao;
import br.edu.ifrn.dominio.Diretoria;
import br.edu.ifrn.dominio.Mailer;
import br.edu.ifrn.dominio.Perfil;
import br.edu.ifrn.dominio.Usuario;
import br.edu.ifrn.exception.NegocioException;
import br.edu.ifrn.generic.GenericDAO;
import br.edu.ifrn.mb.generic.GenericCrudMB;
import br.edu.ifrn.util.FacesUtil;
import br.edu.ifrn.utils.CriptografiaUtil;

public class ManageUsuario extends GenericCrudMB<Usuario> {
	
	private String nomeUsuario;
	private String confirmacaoSenha;
	private boolean renderCoordenador;
	private String senha;
	private UploadedFile csv;
	
	public ManageUsuario() {
		super();
		this.exibirTodosRegistrosAoPesquisar = false;
		if(!FacesUtil.getSessionUser().getUsuario().isAdministrador()){
			this.setWhereScope(" WHERE usuario.diretoria.id = "+FacesUtil.getSessionUser().getDiretoria().getId());
		}
	}
	public String importarDados() {
		return "UsuarioIncluirAlterarLot";
	}
	
	public String incluirLot(){
		try
		{
			String data="";

			//get the uploaded file
			InputStream stream = getCsv().getInputStream();
			ByteArrayOutputStream baos = new ByteArrayOutputStream();

			//get the file size
			int size = (int) getCsv().getSize();

			//define the byte size
			byte buffer[] = new byte[size];
			int bytesRead = 0;

			//read the input
			while( (bytesRead = stream.read(buffer, 0, size)) != -1 )
			{
				baos.write( buffer, 0, bytesRead );
			}

			//assign it to string
			data = new String(baos.toByteArray() );


			int k = 0;
			StringTokenizer st2 = new StringTokenizer(data, "\n\r");
			int dynamicArraySize = st2.countTokens() * 4;

			String[] values = new String[dynamicArraySize];
			while (st2.hasMoreTokens())
			{
				values[k] = st2.nextToken(",\n\r").toString();
				k++;
			};
			
			
			
			criarRegistros(values);
			

			stream.close();
			baos.close();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			FacesUtil.adicionarMensagemErro("Erro ao importar CSV");
		}

		return exibirPesquisa();		
	}

	private void criarRegistros(String[] values) {
		int sucesso = 0;
		String lineErros = "";
		Map<String, Diretoria> diretorias = new HashMap<String, Diretoria>();
		UsuarioDAO usuarioDao = new UsuarioDAO();
		
		int count = 0;
		for (String string : values) {
			count++;
			if(string != null){
				String[] campos = string.split(";"); 
				diretorias = buildDiretorias(campos[5].trim(), diretorias);
				
				Usuario u = new Usuario(campos[0].trim(), campos[1].trim(), campos[2].trim(), campos[3].trim(), Integer.parseInt(campos[4].trim()), Perfil.Professor, diretorias.get(campos[5].trim()));				
				try {
					u.validar();
					usuarioDao.inserir(u);
					sucesso++;
				} catch (NegocioException e) {
					e.printStackTrace();
					lineErros+=count+", ";
				}				
			}
		}		

		FacesUtil.adicionarMensagemAviso(sucesso+" registros foram importandos");
		if(!lineErros.isEmpty()){
			FacesUtil.adicionarMensagemErro("Erro ao importar as seguintes linhas: "+lineErros.substring(0, lineErros.length()-2));
		}
	}

	private Map<String, Diretoria> buildDiretorias(String cod, Map<String, Diretoria> diretorias) {
		
		String cond =  " WHERE diretoria.sigla = '"+cod+"'";
		if(!FacesUtil.getSessionUser().getUsuario().isAdministrador()){
			cond += " AND diretoria.id = "+FacesUtil.getSessionUser().getDiretoria().getId();
		}
		Diretoria d = null;
		if(!diretorias.containsKey(cod)){
			try {
				d = new DiretoriaDAO().consultar(cond);
			} catch (NegocioException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			if(d != null){
				diretorias.put(cod, d);
			}
		}
		
		return diretorias;
	}

	@Override
	protected GenericDAO<Usuario> getDao() {
		return new UsuarioDAO();
	}
	
	public List<AreaAtuacao> getAreasAtuacaoDiretoria(){
		try{
			if(FacesUtil.getSessionUser().getUsuario().isAdministrador() && this.dadosForm != null && this.dadosForm.getDiretoria() != null){
				return new AreaAtuacaoDAO().consultarTodos(" WHERE areaAtuacao.diretoria.id = "+this.dadosForm.getDiretoria().getId(), " ORDER BY areaAtuacao.nome ");
			}else if(!FacesUtil.getSessionUser().getUsuario().isAdministrador()){
				return new AreaAtuacaoDAO().consultarTodos(" WHERE areaAtuacao.diretoria.id = "+FacesUtil.getSessionUser().getDiretoria().getId(), " ORDER BY areaAtuacao.nome ");
			}
		} catch (NegocioException e) {
			FacesUtil.adicionarMensagemErro("Não foi possível consultar as Áreas de Atuação");
			e.printStackTrace();
			return null;
		}
		
		return null;
	}
	public void doNothing(ActionEvent evt){
	}
	@Override
	public String incluir() {
		if(this.dadosForm.getSenha().length()>=6){
			if(this.dadosForm.getSenha().equals(this.confirmacaoSenha)){
				this.senha = this.dadosForm.getSenha();
				this.dadosForm.setSenha(CriptografiaUtil.obterInstancia().criptografarComMD5(this.dadosForm.getSenha()));
				if(!FacesUtil.getSessionUser().getUsuario().isAdministrador()){
					this.dadosForm.setDiretoria(FacesUtil.getSessionUser().getDiretoria());
				}
				return super.incluir();
			}else{
				FacesUtil.adicionarMensagemErro("Confirmação de senha inválida");
				return "";
			}
		}else{
			FacesUtil.adicionarMensagemErro("Campo senha deve conter no mínimo 6 caracteres");
			return "";
		}
	}
	
	@Override
	public String alterar() {
			if(this.dadosForm.getSenha().isEmpty()){
				try {
					this.dadosForm.setSenha(this.getDao().consultarPorId(this.dadosForm.getId()).getSenha());
				} catch (NegocioException e) {
					FacesUtil.adicionarMensagemErro(e);
					return "";
				}
			}else{
				if(this.dadosForm.getSenha().length()>=6){
					if(this.dadosForm.getSenha().equals(this.confirmacaoSenha)){
						this.senha = this.dadosForm.getSenha();
						this.dadosForm.setSenha(CriptografiaUtil.obterInstancia().criptografarComMD5(this.dadosForm.getSenha()));
						return super.alterar();
					}else{
						FacesUtil.adicionarMensagemErro("Confirmação de senha inválida");
						return "";
					}
				}else{
					FacesUtil.adicionarMensagemErro("Campo senha deve conter no mínimo 6 caracteres");
					return "";
				}
			}
			return super.alterar();
			
	}
	
	@Override
	public void alterarImpl() throws NegocioException {
		super.alterarImpl();
		try {
			Mailer.sendMail(FacesUtil.getSessionUser().getUsuario(), this.dadosForm.getEmail(), "[CICC - Administração] "+ "Usuário alterado", "Seu dados foram alterados com sucesso" +
					"\n\n Para acessar o sistema: "+FacesUtil.getContextPath());
		} catch (Exception e) {
			FacesUtil.adicionarMensagemErro("Erro ao enviar email.");
		}
	}
	
	@Override
	public void incluirImpl() throws NegocioException {
		super.incluirImpl();
		try {
			Mailer.sendMail(FacesUtil.getSessionUser().getUsuario(), this.dadosForm.getEmail(), "[CICC - Administração] "+ "Usuário inserido", "Seu usuário foi inserido no sistema. \n Login: "+this.dadosForm.getLogin()+"\n Senha: "+ this.senha+"" +
					"\n\n Para acessar o sistema: "+FacesUtil.getContextPath());
		} catch (Exception e) {
			FacesUtil.adicionarMensagemErro("Erro ao enviar email.");
		}
	}
	
	@Override
	public String exibirAlteracao(){
		String retorno = super.exibirAlteracao();
		if(this.dadosForm.isCoordenador()){
			this.setRenderCoordenador(true);
		}
		return retorno;
	}
	@Override
	public String getTitulo() {
		return "Usuário";
	}

	public void setNomeUsuario(String nomeUsuario) {
		this.nomeUsuario = nomeUsuario;
	}

	public String getNomeUsuario() {
		return nomeUsuario;
	}
	
	public void filtrar() throws NegocioException {
		if(FacesUtil.getSessionUser().getUsuario().isAdministrador()){
			this.dadosPesquisa = this.getDao().consultarTodos(" WHERE UPPER(usuario.nome) LIKE '%"+this.nomeUsuario.toUpperCase()+"%'", "");
		}else{
			this.dadosPesquisa = this.getDao().consultarTodos(" WHERE UPPER(usuario.nome) LIKE '%"+this.nomeUsuario.toUpperCase()+"%' AND usuario.diretoria.id = "+FacesUtil.getSessionUser().getDiretoria().getId(), "");
		}
	}

	public void setConfirmacaoSenha(String confirmacaoSenha) {
		this.confirmacaoSenha = confirmacaoSenha;
	}

	public String getConfirmacaoSenha() {
		return confirmacaoSenha;
	}
	
	public List<Diretoria> getDiretorias(){
		try {
			return new DiretoriaDAO().consultarTodos();
		} catch (NegocioException e) {
			FacesUtil.adicionarMensagemErro("Não foi possível consultar as diretorias");
			e.printStackTrace();
			return null;
		}
	}

	public void setRenderCoordenador(boolean renderCoordenador) {
		this.renderCoordenador = renderCoordenador;
	}

	public boolean isRenderCoordenador() {
		return renderCoordenador;
	}
	public void setCsv(UploadedFile csv) {
		this.csv = csv;
	}
	public UploadedFile getCsv() {
		return csv;
	}
}
